package com.seven.first.suite.util;

import org.apache.commons.lang.StringUtils;

public class DesensitizationUtils {

    /**
     * 客户编号。
     * 脱敏规则：保留前3位和最后3位，其它用*代替。
     */
    public static String DesConsNo(String consNo) {
        return DesStr(3, 3, consNo);
    }

    /**
     * 户名（居民客户）、联系人姓名。
     * 脱敏规则：3 个字以内隐藏第 1 个字，4-6 个字隐藏前 2 个字，大于 6 个字隐藏第 3-6个字，隐藏字用*代替。
     * 对于姓名用“·”分为多部分的情况，每部分均采用上述规则进行脱敏。
     */
    public static String DesName(String value) {
        if (value != null && !"".equals(value.trim())) {
            String rtnValue = "";
            if (value.trim().indexOf("·") != -1) {
                String[] str = value.trim().split("·");

                for(int i = 0; i < str.length; ++i) {
                    int len = str[i].length();
                    if (len < 4) {
                        rtnValue = rtnValue + DesStr(0, len - 1, str[i]);
                    } else if (len < 7) {
                        rtnValue = rtnValue + DesStr(0, len - 2, str[i]);
                    } else {
                        rtnValue = rtnValue + DesStr(2, len - 6, str[i]);
                    }

                    if (i < str.length - 1) {
                        rtnValue = rtnValue + "·";
                    }
                }
            } else {
                int len = value.trim().length();
                if (len < 4) {
                    rtnValue = rtnValue + DesStr(0, len - 1, value.trim());
                } else if (len < 7) {
                    rtnValue = rtnValue + DesStr(0, len - 2, value.trim());
                } else {
                    rtnValue = rtnValue + DesStr(2, len - 6, value.trim());
                }
            }

            return rtnValue;
        } else {
            return value;
        }
    }

    /**
     * 户名（企业客户）。
     * 按长度分阶梯保留；长度4个字及以下的，首尾各保留1个字；长度5-6个字的，首尾各保留2个字。
     * 长度7个字及以上奇数，隐去中间3个字；长度8个字及以上偶数，隐去中间4个字；隐藏字用*代替。
     */
    public static String DesCompany(String value) {
        if (null != value && !"".equals(value)) {
            String rtnValue = "";
            int len = value.length();
            if (len < 3) {
                rtnValue = value;
            } else {
//                int keepLen = false;
                int keepLen;
                if (len < 5) {
                    keepLen = 1;
                } else if (len < 7) {
                    keepLen = 2;
                } else if (len % 2 == 1) {
                    keepLen = (len - 3) / 2;
                } else {
                    keepLen = (len - 4) / 2;
                }

                rtnValue = rtnValue + DesStr(keepLen, keepLen, value.trim());
            }

            return rtnValue;
        } else {
            return value;
        }
    }

    /**
     * 网站账户。
     * 分段屏蔽，每隔2位用*替换2位。
     */
    public static String DesWebAccount(String value) {
        if (null != value && !"".equals(value)) {
            String rtnValue = "";
            int len = value.length();
            int remainder = len % 4;

            for(int i = 1; i * 4 <= len; ++i) {
                rtnValue = rtnValue + DesStr(2, 0, value.substring((i - 1) * 4, i * 4));
            }

            if (remainder != 3) {
                rtnValue = rtnValue + value.substring(len - remainder);
            } else {
                rtnValue = rtnValue + value.substring(len - remainder, len - 1) + "*";
            }

            return rtnValue;
        } else {
            return value;
        }
    }

    /**
     * 用电地址（结构化）。
     * 取结构化地址“省+市+区县+街道/乡镇+居委会/村+道路+小区+门牌号”中“省+市+区县+门牌号”部分。
     * 门牌号保留最后5位，中间用6个*代替。
     */
    public static String DesElectAddr(String value) {
        if (null != value && !"".equals(value)) {
            int len = value.length();
            int addr = Math.max(value.indexOf("区"), value.indexOf("县"));
            if (addr == -1) {
                return DesVATAccount(value);
            } else {
                StringBuffer tmpBuf = new StringBuffer();
                tmpBuf.append(value.substring(0, addr + 1));

                for(int i = 0; i < 6; ++i) {
                    tmpBuf.append("*");
                }

                tmpBuf.append(value.substring(len - 5, len));
                return tmpBuf.toString();
            }
        } else {
            return value;
        }
    }

    /**
     * 联系人地址、法人地址、增值税注册地址（非结构化）。
     * 按长度分阶梯保留：；长度5个字及以下的，保留第1个字和最后2个字长度6-9个字的，保留最后5个字。
     * 长度为10个字及以上的，隐去最后5个字之前的4个字；隐藏字用*代替。
     */
    public static String DesAddress(String value) {
        if (value != null && !"".equals(value)) {
            String rtnValue = "";
            int len = value.length();
            if (len < 4) {
                rtnValue = value;
            } else if (len < 6) {
                rtnValue = DesStr(1, 2, value);
            } else if (len < 10) {
                rtnValue = DesStr(0, 5, value);
            } else {
                rtnValue = DesStr(len - 9, 5, value);
            }

            return rtnValue;
        } else {
            return value;
        }
    }

    /**
     * 联系电话（手机）。
     * 格式:11位数字，号段3位+归属地编号4位+流水号4位。
     * 脱敏规则:保留前3位和最后3位，其余用*代替。
     */
    public static String DesPhone(String value) {
        return value != null && !"".equals(value) ? DesStr(3, 3, value) : value;
    }

    /**
     * 联系电话（固定电话）。
     * 格式:区号+3-4位区域信息+4位流水号。
     * 脱敏规则:区号不隐藏，7-8位电话号码保留最后3位，其余用*代替。
     */
    public static String DesTelephon(String value) {
        return value != null && !"".equals(value) ? DesStr(value.indexOf("-") + 1, 3, value) : value;
    }

    /**
     * 电子邮箱。
     * 格式:邮箱名+@+邮件服务器地址。
     * 脱敏规则:“@”前小于等于5位的，隐藏前2位；大于5位的，保留前3位，其余用*代替。
     */
    public static String DesEmail(String value) {
        if (value != null && !"".equals(value)) {
            int loc = value.indexOf("@");
            if (loc < 0) {
                return value;
            } else {
                String rtnValue = "";
                int len = value.length();
                if (loc < 6) {
                    int tmp = Math.min(2, loc);
                    rtnValue = DesStr(0, len - tmp, value);
                } else if (loc > 5) {
                    rtnValue = DesStr(3, len - loc, value);
                }

                return rtnValue;
            }
        } else {
            return value;
        }
    }

    /**
     * 微信账号。
     * 格式:6-20位大写字母、小写字母、数字、下划线、减号、点的组合。
     * 脱敏规则:分段屏蔽，每隔2位用*替换2位。
     */
    public static String DesWeChat(String value) {
        if (value != null && !"".equals(value)) {
            int len = value.length();
            if (len >= 6 && len <= 20) {
                String rtnValue = "";
                int remainder = len % 4;

                for(int i = 1; i * 4 <= len; ++i) {
                    rtnValue = rtnValue + DesStr(2, 0, value.substring((i - 1) * 4, i * 4));
                }

                if (remainder != 3) {
                    rtnValue = rtnValue + value.substring(len - remainder);
                } else {
                    rtnValue = rtnValue + value.substring(len - remainder, len - 1) + "*";
                }

                return rtnValue;
            } else {
                return value;
            }
        } else {
            return value;
        }
    }

    /**
     * QQ号。
     * 格式5-10位不定长数字。
     * 脱敏规则:保留前2位和最后1位，其余用*代替。
     */
    public static String DesQQ(String value) {
        if (value != null && !"".equals(value)) {
            int len = value.length();
            return len >= 5 && len <= 10 ? DesStr(2, 1, value) : value;
        } else {
            return value;
        }
    }

    /**
     * 增值税账户。
     * 8-28位数字，为银行对公账户。
     * 脱敏规则:保留最后4位，其余用*代替。
     */
    public static String DesVAT(String addvalue) {
        if (addvalue != null && !"".equals(addvalue)) {
            int len = addvalue.length();
            String rtnValue = addvalue;
            if (len > 7 && len < 29) {
                rtnValue = DesStr(0, 4, addvalue);
            }

            return rtnValue;
        } else {
            return addvalue;
        }
    }

    /**
     * 增值税税号。
     * 15-20位不定长数字。
     * 脱敏规则:保留前4位和最后4位，其余用*代替。
     */
    public static String DesVATAccount(String addvalue) {
        if (addvalue != null && !"".equals(addvalue)) {
            int len = addvalue.length();
            String rtnValue = addvalue;
            if (len > 14 && len < 21) {
                rtnValue = DesStr(4, 4, addvalue);
            }

            return rtnValue;
        } else {
            return addvalue;
        }
    }

    /**
     * 存折账号。
     * 14-19位数字。
     * 脱敏规则:保留前4位和最后4位，中间用*代替。
     */
    public static String DesBankBookNum(String addvalue) {
        if (addvalue != null && !"".equals(addvalue)) {
            int len = addvalue.length();
            String rtnValue = addvalue;
            if (len > 13 && len < 20) {
                rtnValue = DesStr(4, 4, addvalue);
            }

            return rtnValue;
        } else {
            return addvalue;
        }
    }

    /**
     * 银行卡号。
     * 13-19位数字。
     * 脱敏规则:保留前4位和最后4位，中间用*代替。
     */
    public static String DesBankCardNum(String bankNum) {
        if (bankNum != null && !"".equals(bankNum)) {
            int len = bankNum.length();
            String rtnValue = bankNum;
            if (len > 12 && len < 20) {
                rtnValue = DesStr(4, 4, bankNum);
            }

            return rtnValue;
        } else {
            return bankNum;
        }
    }

    /**
     * 车架号。
     * 17位字母和数字组合。
     * 脱敏规则: 保留最后6位，其余用*代替。
     */
    public static String DesFrameNumber(String frameNumber) {
        if (frameNumber != null && !"".equals(frameNumber)) {
            int len = frameNumber.length();
            String rtnValue = frameNumber;
            if (len == 17) {
                rtnValue = DesStr(0, 6, frameNumber);
            }

            return rtnValue;
        } else {
            return frameNumber;
        }
    }

    /**
     *  车牌号。
     *  1个汉字+1个字母+5位字母和数字组合流水号，流水号前为地区编码。
     *  脱敏规则:保留地区编码和流水号最后2位，其余用*代替。
     */
    public static String DesLicensePlateNum(String licenseNum) {
        if (licenseNum != null && !"".equals(licenseNum)) {
            int len = licenseNum.length();
            String rtnValue = licenseNum;
            if (len == 7) {
                rtnValue = DesStr(2, 2, licenseNum);
            }

            return rtnValue;
        } else {
            return licenseNum;
        }
    }

    /**
     * 台胞证号。
     * 8位数字，流水号。
     * 脱敏规则:保留第5-8位，其余用*代替。
     */
    public static String DesTaiwanCompatriotsNum(String licenseNum) {
        if (licenseNum != null && !"".equals(licenseNum)) {
            int len = licenseNum.length();
            String rtnValue = licenseNum;
            if (len == 8) {
                rtnValue = DesStr(0, 4, licenseNum);
            }

            return rtnValue;
        } else {
            return licenseNum;
        }
    }

    /**
     * 护照号。
     * 1位字母+8位数字，字母代表护照种类，数字为流水号。
     * 脱敏规则:保留1位字母和最后3位数字，其余用*代替。
     */
    public static String DesPassportNum(String passportNum) {
        if (passportNum != null && !"".equals(passportNum)) {
            int len = passportNum.length();
            String rtnValue = passportNum;
            if (len == 9) {
                rtnValue = DesStr(1, 3, passportNum);
            }

            return rtnValue;
        } else {
            return passportNum;
        }
    }

    /**
     * 军人证号。
     * 汉字和数字组合字符串，军种3个汉字+番号4位数字+流水号4位数字。
     * 脱敏规则:保留最后3位，其余用*代替。
     */
    public static String DesSoldierCardNum(String soldierNum) {
        if (soldierNum != null && !"".equals(soldierNum)) {
            int len = soldierNum.length();
            String rtnValue = soldierNum;
            if (len == 11) {
                rtnValue = DesStr(3, 3, soldierNum);
            }

            return rtnValue;
        } else {
            return soldierNum;
        }
    }

    /**
     * 居民身份证号、驾驶证号。
     * 18位数字，6位地区编号+8位出生日期+4位序号。
     * 脱敏规则:保留前6位和最后4位，其余用*代替。
     */
    public static String DesIdNumLiscenceNum(String num) {
        if (num != null && !"".equals(num)) {
            int len = num.length();
            String rtnValue = num;
            if (len == 18) {
                rtnValue = DesStr(6, 4, num);
            }

            return rtnValue;
        } else {
            return num;
        }
    }

    /**
     *  自定义脱敏 通用方法。
     *  @param bgnNum 前置保留值位数
     *  @param endNum 后置保留位数
     *  @param value 待脱敏值
     */
    public static String DesStr(int bgnNum, int endNum, String value) {
        int len = value.length();
        return bgnNum + endNum > len ? value : StringUtils.left(value, bgnNum).concat(StringUtils.leftPad(StringUtils.right(value, endNum), len - bgnNum, "*"));
    }
}
